#pragma once

#include <vex/core/config.h>
#include <atomic>

namespace vex {     
    namespace core {

        struct shared_synchronized_tag {};

        class shared_synchronized {
            std::atomic<int> m_count;
        protected:
            shared_synchronized() : m_count(1)
            {
            }

            VEX_DEFAULTED_DESTRUCTOR(shared_synchronized);

            void add_ref()
            {
                m_count.fetch_add(1, std::memory_order::memory_order_relaxed);
            }

            template<class TDeleter>
            void release(TDeleter p_deleter)
            {
                if (m_count.fetch_add(-1, std::memory_order::memory_order_release) == 1) {
                    std::atomic_thread_fence(std::memory_order::memory_order_acquire);
                    p_deleter();
                }
            }

            bool has_synchronized_ref_count() const
            {
                return true;
            }

            virtual bool is_shareable() const
            {
                return true;
            }
        public:
            typedef shared_synchronized_tag ownership_type;
        };
    }

    using core::shared_synchronized;
    using core::shared_synchronized_tag;
}